#ifndef GRID_H
#define GRID_H

#include "cell.h"
#include "supcell.h"
#include <vector>


/*! @brief A GridModel object is a generic "grid" in 3 dimensions. A gridModel can contains 2 kind of object :
/*  Single "Cell", only use to track the "state" of a cell, and Real Cell   */
template <class T>
class Grid
{
    public:

    /*****************************************
    /*          Constructors
    /*****************************************/

        /*! @brief Default constructor, using default values */
        Grid();

        /*! @brief Initialize the Grid for 1D usage    */
        Grid(int width);

        /*! @brief Initialize the Grid for 2D usage    */
        Grid(int width, int height);

        /*! @brief Initialize the Grid for 3D usage     */
        Grid(int width, int height, int depth);

    /*****************************************
    /*          Properties
    /*****************************************/

        /*****************************************
        /*          Accessors
        /*****************************************/

            /*! @brief Return the current Width of the Grid     */
            int Width()      {   return m_Width;     }

            /*! @brief Return the current Height of the Grid    */
            int Height()     {   return m_Height;    }

            /*! @brief Return the current Depth of the Grid     */
            int Depth()      {   return m_Depth;     }

    /*****************************************
    /*          Methods
    /*****************************************/

        /*****************************************
        /*          Members
        /*****************************************/

            /*! @brief Set to null all "Cells" used by the current SupCell  */
            void Remove(SupCell<T> * cell);

            /*! @brief This function will fill the basic cell with reference to the specified supCell   */
            void FillSpace(SupCell<T> * cell);

            /*! @brief  This function will try to add the specified SupCell at the desired location.
            /*  If it fail, it return false, otherwise, it return the true value    */
            bool Insert(SupCell<T> * cell, int x, int y, int z);

            /*! @brief Check if it's possible to add the SupCell "cell", at the specified location  */
            bool IsThereEnoughSpace(int x, int y, int z, SupCell<T>  * cell);

            /*! @brief Check if It's possible to add the SupCell "Cell" at the specified location, but in 2D */
            bool IsThereEnoughSpace(int x, int y, SupCell<T> * cell);

    private :

    /*****************************************
    /*          Properties
    /*****************************************/

        /*****************************************
        /*          Members
        /*****************************************/

            Cell<T> ***                m_Cells;        /*!< Store the base cells of the current Grid       */
            std::vector<SupCell<T>>    m_SupCells;     /*!< Store all the "SupCell" of the current Grid    */


            int     m_Width;        /*!< Width  of the current Grid   */
            int     m_Height;       /*!< Height of the current Grid   */
            int     m_Depth;        /*!< Depth  of the current Grid   */

        /*****************************************
        /*          Statics
        /*****************************************/

            static  int     s_DefaultWidth      ;
            static  int     s_DefaultHeight     ;
            static  int     s_DefaultDepth      ;

    /*****************************************
    /*          Methods
    /*****************************************/

        /*****************************************
        /*          Members
        /*****************************************/

            /*! @brief Initialize the Cell Array according to current Grid Width and Height */
            void InitializeCells();

            void Initialize(int width, int height, int depth);



};
#endif // GRID_H
